package com.autumn.log.client.logback;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;

import com.autumn.spring.boot.context.AutumnApplicationContext;
import com.autumn.util.WebUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.UnsynchronizedAppenderBase;

/**
 * 基于 Logback 的队列日志
 * 
 * @author 老码农
 *         <p>
 *         Description
 *         </p>
 * @date 2018-01-12 00:32:40
 */
public class AutumnLogbackMqAppender extends UnsynchronizedAppenderBase<ILoggingEvent> implements DisposableBean {

	private final static Queue<ILoggingEvent> LOG_EVENT_QUERY = new LinkedBlockingQueue<>();

	private final int bufferSize;

	/**
	 * 
	 */
	public AutumnLogbackMqAppender() {
		this.bufferSize = 100000;
	}

	private volatile AutumnLoggingClient autumnLogClient = null;

	/**
	 * 获取日志客户端
	 * 
	 * @return
	 *
	 */
	private AutumnLoggingClient getAutumnLogClient() {
		if (autumnLogClient != null) {
			return autumnLogClient;
		}
		synchronized (this) {
			if (autumnLogClient != null) {
				return autumnLogClient;
			}
			ApplicationContext context = AutumnApplicationContext.getContext();
			if (context == null) {
				return null;
			}
			if (context.containsBean(AutumnLoggingClient.LOGGING_BEAN_NAME)) {
				try {
					autumnLogClient = context.getBean(AutumnLoggingClient.class);
					if (LOG_EVENT_QUERY.size() > 0) {
						autumnLogClient.send(LOG_EVENT_QUERY);
						LOG_EVENT_QUERY.clear();
					}
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
			return autumnLogClient;
		}
	}

	@Override
	protected void append(ILoggingEvent eventObject) {
		try {
			AutumnLoggingClient client = this.getAutumnLogClient();
			if (client != null) {
				client.send(eventObject, WebUtils.getCurrentRequestAddress());
			} else {
				if (LOG_EVENT_QUERY.size() < this.bufferSize) {
					LOG_EVENT_QUERY.offer(eventObject);
				} else {
					LOG_EVENT_QUERY.clear();
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace(System.err);
		}
	}

	@Override
	public void destroy() throws Exception {
		LOG_EVENT_QUERY.clear();
	}

	@Override
	public synchronized void start() {
		super.start();
	}

	@Override
	public synchronized void stop() {
		super.stop();
	}

}
